<?php
/**
 * Created by WXCH
 * Date: 2020/1/8 0008 18:06
 */

namespace app\api\service;


use app\lib\enum\ScopeEnum;
use app\lib\exception\ForbiddenException;
use app\lib\exception\ParameterException;
use app\lib\exception\TokenException;
use think\Request;
use think\Cache;
use think\Exception;

class Token{

    /**
     *  生成令牌
     * @return string
     */
    public static function generateToken(){
        $randChar = getRandChar(32);
        $timestamp = $_SERVER["REQUEST_TIME_FLOAT"];
        $tokenSalt = config("secure.token_salt");
        return md5($randChar . $timestamp . $tokenSalt);
    }

    public static function needPrimaryScore(){
        $scope = self::getCurrentTokenVar("scope");
        if($scope){
            if($scope >= ScopeEnum::User){
                return true;
            }else{
                throw new ForbiddenException();
            }
        }else{
            throw new TokenException();
        }
    }

    /**
     *  用户专有权限
     * @return bool
     * @throws Exception
     * @throws ForbiddenException
     * @throws TokenException
     */
    public static function needExclusiveScope(){
        $scope = self::getCurrentTokenVar("scope");
        if ($scope){
            if ($scope == ScopeEnum::User) {
                return true;
            } else {
                throw new ForbiddenException();
            }
        } else {
            throw new TokenException();
        }
    }

    /**
     * 管理员专有权限
     * @return bool
     * @throws Exception
     * @throws ForbiddenException
     * @throws TokenException
     */
    public static function needSuperScope()
    {
        $scope = self::getCurrentTokenVar('scope');
        if ($scope){
            if ($scope == ScopeEnum::Super) {
                return true;
            } else {
                throw new ForbiddenException();
            }
        } else {
            throw new TokenException();
        }
    }

    /**
     * 根据关键词获取当前token值
     * @param $key
     * @return mixed
     * @throws Exception
     * @throws TokenException
     */
    public static function getCurrentTokenVar($key){
        $token = Request::instance()->header("token");
        $vars = Cache::get($token);
        if(!$vars){
            throw new TokenException();
        }else{
            if(!is_array($vars)){
                $vars = json_decode($vars, true);
            }
            if(array_key_exists($key, $vars)){
                return $vars[$key];
            }else{
                throw new Exception("尝试获取的Token变量并不存在");
            }
        }
    }

    /**
     * 从缓存中获取当前用户指定身份标识
     * @param $keys
     * @return array
     * @throws TokenException
     */
    public static function getCurrentIdentity($keys){
        $token = Request::instance()->header("token");
        $identities = Cache::get($token);
        if (!$identities) {
            throw new TokenException();
        } else {
            $identities = json_decode($identities, true);
            $result = [];
            foreach ($keys as $key) {
                if (array_key_exists($key, $identities)) {
                    $result[$key] = $identities[$key];
                }
            }
            return $result;
        }
    }

    /**
     * 获取全局UID
     * @return mixed
     * @throws Exception
     * @throws TokenException
     */
    public static function getCurrentUid(){
        $uid = self::getCurrentTokenVar('uid');
        $scope = self::getCurrentTokenVar('scope');
        if ($scope == ScopeEnum::Super) {
            $userID = input('get.uid');
            if (!$userID) {
                throw new ParameterException(
                    [
                        'msg' => '没有指定需要操作的用户对象'
                    ]);
            }
            return $userID;
        } else {
            return $uid;
        }
    }

    /**
     * 检查操作UID是否合法
     * @param $checkedUID
     * @return bool
     * @throws Exception
     * @throws ParameterException
     * @throws TokenException
     */
    public static function isValidOperate($checkedUID){
        if(!$checkedUID){
            throw new Exception('检查UID时必须传入一个被检查的UID');
        }
        $currentOperateUID = self::getCurrentUid();
        if($currentOperateUID == $checkedUID){
            return true;
        }
        return false;
    }

    /**
     * 验证token值
     * @param $token
     * @return bool
     */
    public static function verifyToken($token){
        $exist = Cache::get($token);
        if($exist){
            return true;
        } else{
            return false;
        }
    }
}























